import { computed, inject, nextTick } from "vue"
import { KeyValues, RequestParamConfig, ServiceParamConfig, ApiConfigForm, HttpMethod, ContentType } from "../../utils/types"
import { genKey, isArr, paramDataTypeSelect, treeUtil } from "../../utils"

export const injectKeyOfEditor = Symbol('ApiEditor')

export interface IStepForm {
  validate: () => Promise<any>,
  getForm: () => KeyValues
}

export interface IApiEditorProvider {
  scrollToBottom?: () => void,
  getForm?: () => ApiConfigForm
}

type ParamConfig = RequestParamConfig | ServiceParamConfig

export type ParamConfigProps = {
  isTree?: boolean,
  modelValue: ParamConfig[]
}

export const useParamConfig = (props: ParamConfigProps) => {
  const apiEditor: IApiEditorProvider = inject(injectKeyOfEditor, {})

  const dataTypes = computed(() => {
    return props.isTree ? paramDataTypeSelect.allTypes : paramDataTypeSelect.baseTypes
  })

  const addItem = async () => {
    props.modelValue.push({ _k: genKey() })
    await nextTick()
    apiEditor.scrollToBottom()
  }

  const addSubItem = async (row: ParamConfig) => {
    if (!isArr(row.childrenApiParams)) {
      row.childrenApiParams = []
    }
    row.childrenApiParams.push({ _k: genKey() })
    await nextTick()
    apiEditor.scrollToBottom()
  }

  const removeItem = (row: ParamConfig) => {
    const parNode = treeUtil.findParent({
      data: props.modelValue,
      config: { key: '_k', children: 'childrenApiParams' },
      node: row
    })
    const childs = parNode ? parNode.childrenApiParams : props.modelValue
    childs.splice(childs.indexOf(row), 1)
  }

  const canAddChild = (row: ParamConfig) => {
    return props.isTree &&
      [paramDataTypeSelect.OBJECT, paramDataTypeSelect.ARRAY].includes(row.paramType)
  }

  const disableType = (row: ParamConfig) => (row.childrenApiParams || []).length > 0

  return {
    apiEditor,
    dataTypes,
    addItem,
    addSubItem,
    removeItem,
    disableType,
    canAddChild
  }
}

export const useConfig = (props: { modelValue: ApiConfigForm }) => {
  const isPutOrPost = computed(() => {
    return [HttpMethod.POST, HttpMethod.PUT].includes(props.modelValue.method)
  })

  const isTree = computed(() => {
    return props.modelValue.requestType === ContentType.JSON && isPutOrPost.value
  })

  return { isPutOrPost, isTree }
}
